
/********************************************************************************
 * Copyright (c) 2019 [Open Lowcode SAS](https://openlowcode.com/)
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0 .
 *
 * SPDX-License-Identifier: EPL-2.0
 ********************************************************************************/

package org.openlowcode.server.runtime;

import java.util.logging.Logger;

import org.openlowcode.module.system.data.Appuser;
import org.openlowcode.module.system.data.Authority;
import org.openlowcode.module.system.data.Domain;
import org.openlowcode.module.system.data.Groupadminlink;
import org.openlowcode.module.system.data.Groupmemberlink;
import org.openlowcode.module.system.data.Groupswithauthority;
import org.openlowcode.module.system.data.Usergroup;

/**
 * This gathers common code used in SModule to avoid bloat in the autogenerated
 * SModule code.
 * 
 * @author <a href="https://openlowcode.com/" rel="nofollow">Open Lowcode
 *         SAS</a>
 *
 */
public class SModuleHelper {
	private static Logger logger = Logger.getLogger(SModuleHelper.class.getName());

	/**
	 * creates a link between a group and an authority
	 * 
	 * @param authority authority to link to the group (should be persisted)
	 * @param group     group to link to the authority (should be persisted)
	 */
	public static void createGroupWithAuthorityIfNotExists(Authority authority, Usergroup group) {
		Groupswithauthority oldlinks[] = Groupswithauthority.getalllinksfromleftandrightid(authority.getId(),
				group.getId(), null);
		if (oldlinks.length == 0) {
			Groupswithauthority newlink = new Groupswithauthority();
			newlink.setleftobject(authority.getId());
			newlink.setrightobject(group.getId());
			newlink.insert();
			logger.info("linked authority '" + authority.getNr() + "' to group '" + group.getNr() + "'");
		}
	}

	/**
	 * This will check if the authority exists, and creates it, or updates secondary
	 * fields if this has changed
	 * 
	 * @param the    unique number, including prefix on module
	 * @param name   a clear name
	 * @param scope  precision on the scope in clear text
	 * @param domain parent domain
	 * @return the authority as created or updated or found correct
	 */

	public static Authority createAuthorityIfNotExists(String number, String name, String scope, Domain domain) {
		Authority[] existingauthorities = Authority.getobjectbynumber(number);
		Authority authority = null;
		if (existingauthorities.length == 0) {
			authority = new Authority();
			authority.setobjectnumber(number);
			authority.setobjectname(name);
			authority.setScope(scope);
			authority.setparentforscope(domain.getId());
			authority.insert();
			logger.info("create authority " + number + " for scope " + domain.getNr());
		} else {
			authority = existingauthorities[0];
			boolean toupdate = false;
			if (!(name).equals(authority.getObjectname())) {
				authority.setobjectname(name);
				toupdate = true;
			}
			if (!(scope).equals(authority.getScope())) {
				authority.setScope(scope);
				toupdate = true;
			}
			if (toupdate)
				authority.update();
		}
		return authority;
	}

	/**
	 * This method will create an usergroup
	 * 
	 * @param number      the unique number, including prefix on module and domain
	 * @param description a clear text description
	 * @return the user group as created or updated or found correct
	 */

	public static Usergroup createUserGroupIfNotExists(String number, String description) {
		Usergroup usergroup = null;
		Usergroup[] existingusergroups = Usergroup.getobjectbynumber(number);
		if (existingusergroups.length == 0) {
			usergroup = new Usergroup();
			usergroup.setobjectnumber(number);
			usergroup.setDescription(description);
			usergroup.insert();
			logger.info("create group " + number);
		} else {
			usergroup = existingusergroups[0];
			boolean toupdate = false;
			if (!(description).equals(usergroup.getDescription())) {
				usergroup.setDescription(description);
				toupdate = true;
			}
			if (toupdate)
				usergroup.update();
		}

		return usergroup;
	}

	/**
	 * this method will check if the user is already registered as admin of the
	 * group, and else add it
	 * 
	 * @param group the group object
	 * @param user  user to add as admin of the group
	 */
	public static void createAdminLinkForGroupIfNotExists(Usergroup group, Appuser user) {
		Groupadminlink[] oldadminlink = Groupadminlink.getalllinksfromleftandrightid(group.getId(), user.getId(), null);
		if (oldadminlink.length == 0) {
			Groupadminlink adminlink = new Groupadminlink();
			adminlink.setleftobject(group.getId());
			adminlink.setrightobject(user.getId());
			adminlink.insert();
			logger.info("Added user '" + user.getNr() + "' as admin of group '" + group.getNr() + "'");
		}
	}

	/**
	 * this method will check if the user is already registered as member of the
	 * group, and else add it
	 * 
	 * @param group group
	 * @param user  user to add if needed as member of the group
	 */
	public static void createMemberLinkForGroupIfNotExists(Usergroup group, Appuser user) {
		Groupmemberlink[] oldmemberlink = Groupmemberlink.getalllinksfromleftandrightid(group.getId(), user.getId(),
				null);
		if (oldmemberlink.length == 0) {
			Groupmemberlink adminlink = new Groupmemberlink();
			adminlink.setleftobject(group.getId());
			adminlink.setrightobject(user.getId());
			adminlink.insert();
			logger.info("Added user '" + user.getNr() + "' as member of group '" + group.getNr() + "'");
		}
	}

	/**
	 * @param number       number of the domain
	 * @param parentdomain parent domain in the domain hierarchy
	 * @return the domain that was queried or inserted if required
	 */
	public static Domain createDomainIfNotExists(String number, Domain parentdomain) {
		Domain existingdomains[] = Domain.getobjectbynumber(number);
		Domain domain = null;
		if (existingdomains.length == 0) {
			domain = new Domain();
			domain.setobjectnumber(number);
			domain.setparentforhierarchy(parentdomain.getId());
			domain.insert();
			logger.info("create domain " + number + " as parent of " + parentdomain.getNr());
		} else {
			domain = existingdomains[0];
		}
		return domain;
	}

	/**
	 * creates a local user (not managed in enterprise LDAP), typically an admin
	 * 
	 * @param objectnumber user unique business id
	 * @param password     password
	 * @param email        e-mail of the user
	 * @param lastname     last name of the user
	 * @param firstname    first name of the user
	 * @return existing user, or user if created
	 */
	public static Appuser createUserIfNotExists(String objectnumber, String password, String email, String lastname,
			String firstname) {
		Appuser user = null;
		Appuser[] existingusers = Appuser.getobjectbynumber(objectnumber);
		if (existingusers.length == 0) {
			user = new Appuser();
			user.setobjectnumber(objectnumber);
			user.setPassword(password);
			user.setEmail(email);
			user.setLastname(lastname);
			user.setFirstname(firstname);
			user.insert();
			logger.info("create appuser '" + objectnumber + "'");
		} else {
			user = existingusers[0];
		}
		return user;
	}
}
